package service

import (
	"admin-system/internal/config"
	"admin-system/internal/model"
	"errors"
	"fmt"

	"gorm.io/gorm"
)

// RoleService 角色服务
type RoleService struct{}

// NewRoleService 创建角色服务实例
func NewRoleService() *RoleService {
	return &RoleService{}
}

// List 获取角色列表
func (s *RoleService) List(page, pageSize int, keyword string) ([]model.Role, int64, error) {
	var roles []model.Role
	var total int64

	db := config.DB

	// 构建查询条件
	query := db.Model(&model.Role{})
	if keyword != "" {
		query = query.Where("name LIKE ? OR description LIKE ?",
			"%"+keyword+"%", "%"+keyword+"%")
	}

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, fmt.Errorf("获取角色总数失败: %v", err)
	}

	// 分页查询
	offset := (page - 1) * pageSize
	if err := query.Offset(offset).Limit(pageSize).Order("id ASC").Find(&roles).Error; err != nil {
		return nil, 0, fmt.Errorf("获取角色列表失败: %v", err)
	}

	return roles, total, nil
}

// GetByID 根据ID获取角色
func (s *RoleService) GetByID(id uint) (*model.Role, error) {
	var role model.Role
	if err := config.DB.First(&role, id).Error; err != nil {
		return nil, fmt.Errorf("角色不存在: %v", err)
	}
	return &role, nil
}

// GetByIDWithRelations 根据ID获取角色及其关联的权限和菜单
func (s *RoleService) GetByIDWithRelations(id uint) (*model.Role, error) {
	var role model.Role
	if err := config.DB.Preload("Permissions").Preload("Menus").First(&role, id).Error; err != nil {
		return nil, fmt.Errorf("角色不存在: %v", err)
	}
	return &role, nil
}

// Create 创建角色
func (s *RoleService) Create(req *model.RoleCreateRequest) (*model.Role, error) {
	// 检查角色名是否已存在
	var existingRole model.Role
	if err := config.DB.Where("name = ?", req.Name).First(&existingRole).Error; err == nil {
		return nil, errors.New("角色名已存在")
	}

	// 开始事务
	tx := config.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 创建角色
	role := model.Role{
		Name:        req.Name,
		Description: req.Description,
		Status:      req.Status,
	}

	// 设置默认状态
	if role.Status == 0 {
		role.Status = 1
	}

	if err := tx.Create(&role).Error; err != nil {
		tx.Rollback()
		return nil, fmt.Errorf("创建角色失败: %v", err)
	}

	// 分配权限
	if len(req.PermissionIDs) > 0 {
		if err := s.updateRolePermissions(tx, role.ID, req.PermissionIDs); err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("分配权限失败: %v", err)
		}
	}

	// 分配菜单
	if len(req.MenuIDs) > 0 {
		if err := s.updateRoleMenus(tx, role.ID, req.MenuIDs); err != nil {
			tx.Rollback()
			return nil, fmt.Errorf("分配菜单失败: %v", err)
		}
	}

	tx.Commit()
	return &role, nil
}

// Update 更新角色
func (s *RoleService) Update(id uint, req *model.RoleUpdateRequest) (*model.Role, error) {
	// 检查角色是否存在
	role, err := s.GetByID(id)
	if err != nil {
		return nil, err
	}

	// 检查角色名是否被其他角色使用
	if req.Name != role.Name {
		var existingRole model.Role
		if err := config.DB.Where("name = ? AND id != ?", req.Name, id).First(&existingRole).Error; err == nil {
			return nil, errors.New("角色名已被其他角色使用")
		}
	}

	// 更新角色信息
	role.Name = req.Name
	role.Description = req.Description
	role.Status = req.Status

	if err := config.DB.Save(role).Error; err != nil {
		return nil, fmt.Errorf("更新角色失败: %v", err)
	}

	return role, nil
}

// Delete 删除角色
func (s *RoleService) Delete(id uint) error {
	// 检查角色是否存在
	role, err := s.GetByID(id)
	if err != nil {
		return err
	}

	// 检查角色是否被用户使用
	var count int64
	if err := config.DB.Model(&model.UserRole{}).Where("role_id = ?", id).Count(&count).Error; err != nil {
		return fmt.Errorf("检查角色使用情况失败: %v", err)
	}

	if count > 0 {
		return errors.New("角色正在被用户使用，无法删除")
	}

	// 开始事务
	tx := config.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 删除角色权限关联
	if err := tx.Where("role_id = ?", id).Delete(&model.RolePermission{}).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("删除角色权限关联失败: %v", err)
	}

	// 删除角色菜单关联
	if err := tx.Where("role_id = ?", id).Delete(&model.RoleMenu{}).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("删除角色菜单关联失败: %v", err)
	}

	// 删除角色
	if err := tx.Delete(role).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("删除角色失败: %v", err)
	}

	tx.Commit()
	return nil
}

// UpdateStatus 更新角色状态
func (s *RoleService) UpdateStatus(id uint, status int8) error {
	// 检查角色是否存在
	role, err := s.GetByID(id)
	if err != nil {
		return err
	}

	// 更新状态
	role.Status = status
	if err := config.DB.Save(role).Error; err != nil {
		return fmt.Errorf("更新角色状态失败: %v", err)
	}

	return nil
}

// UpdatePermissions 更新角色权限
func (s *RoleService) UpdatePermissions(id uint, req *model.RolePermissionsUpdateRequest) error {
	// 检查角色是否存在
	_, err := s.GetByID(id)
	if err != nil {
		return err
	}

	// 开始事务
	tx := config.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	if err := s.updateRolePermissions(tx, id, req.PermissionIDs); err != nil {
		tx.Rollback()
		return err
	}

	tx.Commit()
	return nil
}

// UpdateMenus 更新角色菜单
func (s *RoleService) UpdateMenus(id uint, req *model.RoleMenusUpdateRequest) error {
	// 检查角色是否存在
	_, err := s.GetByID(id)
	if err != nil {
		return err
	}

	// 开始事务
	tx := config.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	if err := s.updateRoleMenus(tx, id, req.MenuIDs); err != nil {
		tx.Rollback()
		return err
	}

	tx.Commit()
	return nil
}

// GetAll 获取所有角色（用于用户分配）
func (s *RoleService) GetAll() ([]model.Role, error) {
	var roles []model.Role
	if err := config.DB.Where("status = ?", 1).Order("id ASC").Find(&roles).Error; err != nil {
		return nil, fmt.Errorf("获取角色列表失败: %v", err)
	}
	return roles, nil
}

// updateRolePermissions 更新角色权限关联（内部方法）
func (s *RoleService) updateRolePermissions(tx *gorm.DB, roleID uint, permissionIDs []uint) error {
	// 删除现有权限关联
	if err := tx.Where("role_id = ?", roleID).Delete(&model.RolePermission{}).Error; err != nil {
		return fmt.Errorf("删除现有权限关联失败: %v", err)
	}

	// 添加新的权限关联
	for _, permissionID := range permissionIDs {
		rolePermission := model.RolePermission{
			RoleID:       roleID,
			PermissionID: permissionID,
		}
		if err := tx.Create(&rolePermission).Error; err != nil {
			return fmt.Errorf("创建权限关联失败: %v", err)
		}
	}

	return nil
}

// updateRoleMenus 更新角色菜单关联（内部方法）
func (s *RoleService) updateRoleMenus(tx *gorm.DB, roleID uint, menuIDs []uint) error {
	// 删除现有菜单关联
	if err := tx.Where("role_id = ?", roleID).Delete(&model.RoleMenu{}).Error; err != nil {
		return fmt.Errorf("删除现有菜单关联失败: %v", err)
	}

	// 添加新的菜单关联
	for _, menuID := range menuIDs {
		roleMenu := model.RoleMenu{
			RoleID: roleID,
			MenuID: menuID,
		}
		if err := tx.Create(&roleMenu).Error; err != nil {
			return fmt.Errorf("创建菜单关联失败: %v", err)
		}
	}

	return nil
}

// GetRolePermissions 获取角色的权限列表
func (s *RoleService) GetRolePermissions(roleID uint) ([]model.Permission, error) {
	var permissions []model.Permission

	err := config.DB.Table("permissions").
		Select("permissions.*").
		Joins("JOIN role_permissions ON permissions.id = role_permissions.permission_id").
		Where("role_permissions.role_id = ? AND permissions.status = 1", roleID).
		Find(&permissions).Error

	if err != nil {
		return nil, fmt.Errorf("获取角色权限失败: %v", err)
	}

	return permissions, nil
}

// GetRoleMenus 获取角色的菜单列表
func (s *RoleService) GetRoleMenus(roleID uint) ([]model.Menu, error) {
	var menus []model.Menu

	err := config.DB.Table("menus").
		Select("menus.*").
		Joins("JOIN role_menus ON menus.id = role_menus.menu_id").
		Where("role_menus.role_id = ? AND menus.status = 1", roleID).
		Order("menus.sort ASC").
		Find(&menus).Error

	if err != nil {
		return nil, fmt.Errorf("获取角色菜单失败: %v", err)
	}

	return menus, nil
}
